package main

import (
	"context"
	"github.com/micro/go-micro/v2"
	"github.com/micro/go-micro/v2/broker"
	"github.com/micro/go-micro/v2/broker/nats"
	"github.com/micro/go-plugins/wrapper/trace/opentracing/v2"
	"github.com/pkg/errors"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readpref"
	"log"
	"time"
	"todolist/achievement-srv/repository"
	"todolist/achievement-srv/subscriber"
	"todolist/common/tracer"
)

const (
	MONGO_URI  = "mongodb://june:june123@139.155.239.206:27017/todolist"
	ServerName = "go.micro.service.achievement"
	JaegerAddr = "139.155.239.206:6831"
)

func main() {
	log.SetFlags(log.Llongfile)
	conn, err := connectMongo(MONGO_URI, time.Second)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Disconnect(context.Background())

	// WrapSubscriber() 订阅中间件
	jaegerTracer, closer, err := tracer.NewJaegerTracer(ServerName, JaegerAddr)
	if err != nil {
		log.Fatal(err)
	}
	defer closer.Close()

	service := micro.NewService(
		micro.Name("go.micro.service.achievement"),
		micro.Version("latest"),
		// 新增消息中间件nats
		micro.Broker(nats.NewBroker(
			broker.Addrs("nats://139.155.239.206:4222"),
		)),

		// 新增链路追踪jaeger
		micro.WrapSubscriber(
			opentracing.NewSubscriberWrapper(jaegerTracer),
		),
	)

	service.Init()

	handler := &subscriber.AchievementSub{
		Repo: &repository.AchievementRepoImpl{
			Conn: conn,
		}}

	// 这里的topic注意与task-srv注册的要一致
	// micro.RegisterSubscriber()方法，第三个参数handler其实是个interface{}，既可以传入一个对象，
	// 也可以直接传入方法（方法参数和返回值结构同上），当我们直接传入具体方法时，就会使用我们指定的方法处理业务
	if err = micro.RegisterSubscriber("go.micro.service.task.finished",
		service.Server(), handler); err != nil {
		log.Fatal(errors.WithMessage(err, "subscribe"))
	}

	if err = service.Run(); err != nil {
		log.Fatal(errors.WithMessage(err, "run server"))
	}
}

func connectMongo(uri string, timeout time.Duration) (*mongo.Client, error) {
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
	if err != nil {
		return nil, errors.WithMessage(err, "connect mongo failed")
	}

	if err = client.Ping(ctx, readpref.Primary()); err != nil {
		return nil, errors.WithMessage(err, "ping mongo failed")
	}

	return client, nil
}
